import sys
import os
import cv2
import numpy as np
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout,
                             QHBoxLayout, QFileDialog, QSlider, QSpinBox, QComboBox,
                             QWidget, QMessageBox, QTabWidget, QGroupBox, QGridLayout,
                             QAction, QToolBar, QStatusBar, QSplitter)
from PyQt5.QtGui import QImage, QPixmap, QPainter, QPen, QColor, QFont
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QPoint, QSize


class ImageProcessor:
    """图像处理核心类"""

    def __init__(self):
        self.image = None
        self.original_image = None
        self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

    def load_image(self, path):
        """加载图像"""
        self.original_image = cv2.imread(path)
        self.image = self.original_image.copy()
        return self.image is not None

    def save_image(self, path):
        """保存图像"""
        if self.image is not None:
            cv2.imwrite(path, self.image)
            return True
        return False

    def rotate(self, angle):
        """旋转图像"""
        if self.image is not None:
            rows, cols = self.image.shape[:2]
            M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
            self.image = cv2.warpAffine(self.image, M, (cols, rows))
            return self.image

    def resize(self, scale):
        """缩放图像"""
        if self.image is not None:
            width = int(self.image.shape[1] * scale / 100)
            height = int(self.image.shape[0] * scale / 100)
            self.image = cv2.resize(self.image, (width, height), interpolation=cv2.INTER_AREA)
            return self.image

    def crop(self, x1, y1, x2, y2):
        """裁剪图像"""
        if self.image is not None:
            self.image = self.image[y1:y2, x1:x2]
            return self.image

    def adjust_brightness_contrast(self, brightness=0, contrast=0):
        """调整亮度和对比度"""
        if self.image is not None:
            alpha = 1.0 + contrast / 100.0
            beta = brightness
            self.image = cv2.convertScaleAbs(self.image, alpha=alpha, beta=beta)
            return self.image

    def smooth(self, method='Gaussian'):
        """图像平滑处理"""
        if self.image is not None:
            if method == 'Gaussian':
                self.image = cv2.GaussianBlur(self.image, (5, 5), 0)
            elif method == 'Median':
                self.image = cv2.medianBlur(self.image, 5)
            elif method == 'Bilateral':
                self.image = cv2.bilateralFilter(self.image, 9, 75, 75)
            return self.image

    def detect_shapes(self):
        """形状识别"""
        if self.image is not None:
            output = self.image.copy()
            gray = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY)
            _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

            contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

            for cnt in contours:
                approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True)
                x, y = approx.ravel()[0], approx.ravel()[1]

                if len(approx) == 3:
                    cv2.drawContours(output, [cnt], -1, (0, 255, 0), 2)
                    cv2.putText(output, "Triangle", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
                elif len(approx) == 4:
                    cv2.drawContours(output, [cnt], -1, (0, 0, 255), 2)
                    cv2.putText(output, "Rectangle", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
                elif 10 > len(approx) > 4:
                    cv2.drawContours(output, [cnt], -1, (255, 0, 0), 2)
                    cv2.putText(output, "Polygon", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
                else:
                    area = cv2.contourArea(cnt)
                    perimeter = cv2.arcLength(cnt, True)
                    if perimeter == 0:
                        continue
                    circularity = 4 * np.pi * area / (perimeter ** 2)
                    if circularity > 0.8:
                        cv2.drawContours(output, [cnt], -1, (0, 255, 255), 2)
                        cv2.putText(output, "Circle", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)

            self.image = output
            return self.image

    def stitch_images(self, images):
        """图像拼接"""
        if len(images) < 2:
            return None

        stitcher = cv2.Stitcher_create()
        status, result = stitcher.stitch(images)

        if status == cv2.Stitcher_OK:
            self.image = result
            return self.image
        else:
            return None

    def detect_faces(self):
        """人脸检测"""
        if self.image is not None:
            output = self.image.copy()
            gray = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY)

            faces = self.face_cascade.detectMultiScale(
                gray,
                scaleFactor=1.1,
                minNeighbors=5,
                minSize=(30, 30)
            )

            for (x, y, w, h) in faces:
                cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 2)

            self.image = output
            return self.image, len(faces)
        return None, 0


class VideoThread(QThread):
    """视频处理线程"""
    update_signal = pyqtSignal(np.ndarray)

    def __init__(self, processor, source=0):
        super().__init__()
        self.processor = processor
        self.source = source
        self.cap = None
        self.running = False
        self.processing_function = None

    def run(self):
        """线程运行函数"""
        self.cap = cv2.VideoCapture(self.source)
        self.running = True

        while self.running:
            ret, frame = self.cap.read()
            if not ret:
                break

            if self.processing_function:
                frame = self.processing_function(frame)

            self.update_signal.emit(frame)
            self.msleep(30)  # 控制帧率

    def stop(self):
        """停止线程"""
        self.running = False
        if self.cap and self.cap.isOpened():
            self.cap.release()
        self.wait()

    def set_processing_function(self, func):
        """设置图像处理函数"""
        self.processing_function = func


class CVPlatform(QMainWindow):
    """计算机视觉开发平台主窗口"""

    def __init__(self):
        super().__init__()
        self.processor = ImageProcessor()
        self.video_thread = None
        self.init_ui()

    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle("计算机视觉开发平台")
        self.setGeometry(100, 100, 1200, 800)

        # 创建菜单栏
        self.create_menu_bar()

        # 创建工具栏
        self.create_tool_bar()

        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QHBoxLayout(central_widget)

        # 左侧面板 - 参数设置
        left_panel = QWidget()
        left_panel.setMaximumWidth(300)
        left_layout = QVBoxLayout(left_panel)

        # 图像处理选项卡
        self.processing_tabs = QTabWidget()
        self.create_image_tabs()
        left_layout.addWidget(self.processing_tabs)

        # 右侧面板 - 图像/视频显示
        right_panel = QWidget()
        right_layout = QVBoxLayout(right_panel)

        # 图像显示区域
        self.image_display = QLabel("请加载图像或视频")
        self.image_display.setAlignment(Qt.AlignCenter)
        self.image_display.setMinimumSize(640, 480)
        self.image_display.setStyleSheet("border: 1px solid #cccccc;")
        right_layout.addWidget(self.image_display)

        # 状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage("就绪")

        # 添加面板到主布局
        main_layout.addWidget(left_panel)
        main_layout.addWidget(right_panel)

        # 裁剪区域选择
        self.crop_start = None
        self.crop_end = None
        self.is_cropping = False

    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()

        # 文件菜单
        file_menu = menubar.addMenu("文件")

        # 加载图像动作
        load_image_action = QAction("加载图像", self)
        load_image_action.setShortcut("Ctrl+I")
        load_image_action.triggered.connect(self.load_image)
        file_menu.addAction(load_image_action)

        # 加载视频动作
        load_video_action = QAction("加载视频", self)
        load_video_action.setShortcut("Ctrl+V")
        load_video_action.triggered.connect(self.load_video)
        file_menu.addAction(load_video_action)

        # 使用摄像头动作
        camera_action = QAction("使用摄像头", self)
        camera_action.setShortcut("Ctrl+C")
        camera_action.triggered.connect(self.use_camera)
        file_menu.addAction(camera_action)

        # 保存图像动作
        save_image_action = QAction("保存图像", self)
        save_image_action.setShortcut("Ctrl+S")
        save_image_action.triggered.connect(self.save_image)
        file_menu.addAction(save_image_action)

        # 分隔线
        file_menu.addSeparator()

        # 退出动作
        exit_action = QAction("退出", self)
        exit_action.setShortcut("Ctrl+Q")
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)

        # 处理菜单
        process_menu = menubar.addMenu("处理")

        # 旋转动作
        rotate_action = QAction("旋转", self)
        rotate_action.triggered.connect(lambda: self.processing_tabs.setCurrentIndex(0))
        process_menu.addAction(rotate_action)

        # 调整动作
        adjust_action = QAction("亮度/对比度", self)
        adjust_action.triggered.connect(lambda: self.processing_tabs.setCurrentIndex(1))
        process_menu.addAction(adjust_action)

        # 平滑动作
        smooth_action = QAction("平滑处理", self)
        smooth_action.triggered.connect(lambda: self.processing_tabs.setCurrentIndex(2))
        process_menu.addAction(smooth_action)

        # 形状识别动作
        shapes_action = QAction("形状识别", self)
        shapes_action.triggered.connect(self.detect_shapes)
        process_menu.addAction(shapes_action)

        # 人脸检测动作
        faces_action = QAction("人脸检测", self)
        faces_action.triggered.connect(self.detect_faces)
        process_menu.addAction(faces_action)

        # 帮助菜单
        help_menu = menubar.addMenu("帮助")

        # 关于动作
        about_action = QAction("关于", self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)

    def create_tool_bar(self):
        """创建工具栏"""
        toolbar = QToolBar("工具栏")
        self.addToolBar(toolbar)

        # 加载图像按钮
        load_image_btn = QAction("加载图像", self)
        load_image_btn.triggered.connect(self.load_image)
        toolbar.addAction(load_image_btn)

        # 加载视频按钮
        load_video_btn = QAction("加载视频", self)
        load_video_btn.triggered.connect(self.load_video)
        toolbar.addAction(load_video_btn)

        # 摄像头按钮
        camera_btn = QAction("摄像头", self)
        camera_btn.triggered.connect(self.use_camera)
        toolbar.addAction(camera_btn)

        # 分隔符
        toolbar.addSeparator()

        # 旋转按钮
        rotate_btn = QAction("旋转", self)
        rotate_btn.triggered.connect(lambda: self.processing_tabs.setCurrentIndex(0))
        toolbar.addAction(rotate_btn)

        # 亮度/对比度按钮
        adjust_btn = QAction("亮度/对比度", self)
        adjust_btn.triggered.connect(lambda: self.processing_tabs.setCurrentIndex(1))
        toolbar.addAction(adjust_btn)

        # 平滑处理按钮
        smooth_btn = QAction("平滑处理", self)
        smooth_btn.triggered.connect(lambda: self.processing_tabs.setCurrentIndex(2))
        toolbar.addAction(smooth_btn)

        # 形状识别按钮
        shapes_btn = QAction("形状识别", self)
        shapes_btn.triggered.connect(self.detect_shapes)
        toolbar.addAction(shapes_btn)

        # 人脸检测按钮
        faces_btn = QAction("人脸检测", self)
        faces_btn.triggered.connect(self.detect_faces)
        toolbar.addAction(faces_btn)

    def create_image_tabs(self):
        """创建图像处理选项卡"""
        # 旋转选项卡
        rotate_tab = QWidget()
        rotate_layout = QVBoxLayout(rotate_tab)

        # 旋转角度滑块
        rotate_group = QGroupBox("旋转")
        rotate_group_layout = QVBoxLayout(rotate_group)

        self.rotate_label = QLabel("旋转角度: 0°")
        self.rotate_slider = QSlider(Qt.Horizontal)
        self.rotate_slider.setRange(0, 359)
        self.rotate_slider.setValue(0)
        self.rotate_slider.valueChanged.connect(self.update_rotate_label)

        rotate_apply_btn = QPushButton("应用旋转")
        rotate_apply_btn.clicked.connect(self.apply_rotate)

        rotate_group_layout.addWidget(self.rotate_label)
        rotate_group_layout.addWidget(self.rotate_slider)
        rotate_group_layout.addWidget(rotate_apply_btn)

        rotate_layout.addWidget(rotate_group)

        # 缩放选项
        scale_group = QGroupBox("缩放")
        scale_group_layout = QVBoxLayout(scale_group)

        self.scale_label = QLabel("缩放比例: 100%")
        self.scale_slider = QSlider(Qt.Horizontal)
        self.scale_slider.setRange(10, 500)
        self.scale_slider.setValue(100)
        self.scale_slider.valueChanged.connect(self.update_scale_label)

        scale_apply_btn = QPushButton("应用缩放")
        scale_apply_btn.clicked.connect(self.apply_scale)

        scale_group_layout.addWidget(self.scale_label)
        scale_group_layout.addWidget(self.scale_slider)
        scale_group_layout.addWidget(scale_apply_btn)

        rotate_layout.addWidget(scale_group)

        # 裁剪选项
        crop_group = QGroupBox("裁剪")
        crop_group_layout = QVBoxLayout(crop_group)

        crop_info_label = QLabel("在图像上拖动鼠标选择裁剪区域")
        self.crop_btn = QPushButton("启用裁剪模式")
        self.crop_btn.clicked.connect(self.toggle_crop_mode)
        self.apply_crop_btn = QPushButton("应用裁剪")
        self.apply_crop_btn.clicked.connect(self.apply_crop)
        self.apply_crop_btn.setEnabled(False)

        crop_group_layout.addWidget(crop_info_label)
        crop_group_layout.addWidget(self.crop_btn)
        crop_group_layout.addWidget(self.apply_crop_btn)

        rotate_layout.addWidget(crop_group)

        rotate_layout.addStretch()

        # 亮度/对比度选项卡
        adjust_tab = QWidget()
        adjust_layout = QVBoxLayout(adjust_tab)

        # 亮度调整
        brightness_group = QGroupBox("亮度")
        brightness_group_layout = QVBoxLayout(brightness_group)

        self.brightness_label = QLabel("亮度: 0")
        self.brightness_slider = QSlider(Qt.Horizontal)
        self.brightness_slider.setRange(-100, 100)
        self.brightness_slider.setValue(0)
        self.brightness_slider.valueChanged.connect(self.update_brightness_label)

        brightness_group_layout.addWidget(self.brightness_label)
        brightness_group_layout.addWidget(self.brightness_slider)

        # 对比度调整
        contrast_group = QGroupBox("对比度")
        contrast_group_layout = QVBoxLayout(contrast_group)

        self.contrast_label = QLabel("对比度: 0")
        self.contrast_slider = QSlider(Qt.Horizontal)
        self.contrast_slider.setRange(-100, 100)
        self.contrast_slider.setValue(0)
        self.contrast_slider.valueChanged.connect(self.update_contrast_label)

        contrast_group_layout.addWidget(self.contrast_label)
        contrast_group_layout.addWidget(self.contrast_slider)

        # 应用按钮
        adjust_apply_btn = QPushButton("应用调整")
        adjust_apply_btn.clicked.connect(self.apply_adjust)

        adjust_layout.addWidget(brightness_group)
        adjust_layout.addWidget(contrast_group)
        adjust_layout.addWidget(adjust_apply_btn)
        adjust_layout.addStretch()

        # 平滑处理选项卡
        smooth_tab = QWidget()
        smooth_layout = QVBoxLayout(smooth_tab)

        smooth_group = QGroupBox("平滑处理")
        smooth_group_layout = QVBoxLayout(smooth_group)

        self.smooth_combo = QComboBox()
        self.smooth_combo.addItems(["Gaussian", "Median", "Bilateral"])

        smooth_apply_btn = QPushButton("应用平滑")
        smooth_apply_btn.clicked.connect(self.apply_smooth)

        smooth_group_layout.addWidget(self.smooth_combo)
        smooth_group_layout.addWidget(smooth_apply_btn)

        smooth_layout.addWidget(smooth_group)
        smooth_layout.addStretch()

        # 添加选项卡
        self.processing_tabs.addTab(rotate_tab, "旋转/缩放/裁剪")
        self.processing_tabs.addTab(adjust_tab, "亮度/对比度")
        self.processing_tabs.addTab(smooth_tab, "平滑处理")

    def load_image(self):
        """加载图像"""
        self.stop_video()

        path, _ = QFileDialog.getOpenFileName(
            self, "选择图像", "", "图像文件 (*.png *.jpg *.jpeg *.bmp)"
        )

        if path:
            if self.processor.load_image(path):
                self.display_image(self.processor.image)
                self.statusBar.showMessage(f"已加载图像: {os.path.basename(path)}")
            else:
                QMessageBox.warning(self, "错误", "无法加载图像")

    def load_video(self):
        """加载视频"""
        self.stop_video()

        path, _ = QFileDialog.getOpenFileName(
            self, "选择视频", "", "视频文件 (*.mp4 *.avi *.mov *.mkv)"
        )

        if path:
            self.video_thread = VideoThread(self.processor, path)
            self.video_thread.update_signal.connect(self.display_image)
            self.video_thread.start()
            self.statusBar.showMessage(f"已加载视频: {os.path.basename(path)}")

    def use_camera(self):
        """使用摄像头"""
        self.stop_video()

        self.video_thread = VideoThread(self.processor, 0)
        self.video_thread.update_signal.connect(self.display_image)
        self.video_thread.start()
        self.statusBar.showMessage("正在使用摄像头")

    def stop_video(self):
        """停止视频播放"""
        if self.video_thread and self.video_thread.isRunning():
            self.video_thread.stop()
            self.video_thread = None

    def save_image(self):
        """保存图像"""
        if self.processor.image is None:
            QMessageBox.warning(self, "错误", "没有可保存的图像")
            return

        path, _ = QFileDialog.getSaveFileName(
            self, "保存图像", "", "图像文件 (*.png *.jpg *.jpeg *.bmp)"
        )

        if path:
            if self.processor.save_image(path):
                self.statusBar.showMessage(f"已保存图像: {os.path.basename(path)}")
            else:
                QMessageBox.warning(self, "错误", "无法保存图像")

    def display_image(self, image):
        """在界面上显示图像"""
        if image is None:
            return

        # 转换为RGB格式
        if len(image.shape) == 3:
            rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        else:
            rgb_image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)

        # 创建QImage
        h, w, ch = rgb_image.shape
        bytes_per_line = ch * w
        q_img = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888)

        # 如果是裁剪模式，绘制裁剪框
        if self.is_cropping and self.crop_start and self.crop_end:
            painter = QPainter(q_img)
            painter.setPen(QPen(QColor(255, 0, 0), 2, Qt.SolidLine))
            x1, y1 = min(self.crop_start.x(), self.crop_end.x()), min(self.crop_start.y(), self.crop_end.y())
            x2, y2 = max(self.crop_start.x(), self.crop_end.x()), max(self.crop_start.y(), self.crop_end.y())
            painter.drawRect(x1, y1, x2 - x1, y2 - y1)
            painter.end()

        # 显示图像
        pixmap = QPixmap.fromImage(q_img)
        self.image_display.setPixmap(pixmap.scaled(
            self.image_display.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
        ))

    def update_rotate_label(self):
        """更新旋转标签"""
        self.rotate_label.setText(f"旋转角度: {self.rotate_slider.value()}°")

    def update_scale_label(self):
        """更新缩放标签"""
        self.scale_label.setText(f"缩放比例: {self.scale_slider.value()}%")

    def update_brightness_label(self):
        """更新亮度标签"""
        self.brightness_label.setText(f"亮度: {self.brightness_slider.value()}")

    def update_contrast_label(self):
        """更新对比度标签"""
        self.contrast_label.setText(f"对比度: {self.contrast_slider.value()}")

    def apply_rotate(self):
        """应用旋转"""
        if self.processor.image is not None:
            angle = self.rotate_slider.value()
            self.processor.rotate(angle)
            self.display_image(self.processor.image)
            self.statusBar.showMessage(f"已旋转 {angle}°")

    def apply_scale(self):
        """应用缩放"""
        if self.processor.image is not None:
            scale = self.scale_slider.value()
            self.processor.resize(scale)
            self.display_image(self.processor.image)
            self.statusBar.showMessage(f"已缩放至 {scale}%")

    def toggle_crop_mode(self):
        """切换裁剪模式"""
        self.is_cropping = not self.is_cropping

        if self.is_cropping:
            self.crop_btn.setText("禁用裁剪模式")
            self.apply_crop_btn.setEnabled(False)
            self.image_display.setCursor(Qt.CrossCursor)
            self.statusBar.showMessage("裁剪模式已启用，请在图像上拖动鼠标选择区域")
        else:
            self.crop_btn.setText("启用裁剪模式")
            self.image_display.setCursor(Qt.ArrowCursor)
            self.statusBar.showMessage("裁剪模式已禁用")
            self.crop_start = None
            self.crop_end = None

    def mousePressEvent(self, event):
        """鼠标按下事件"""
        if self.is_cropping and event.button() == Qt.LeftButton:
            self.crop_start = event.pos()
            self.crop_end = None
            self.apply_crop_btn.setEnabled(False)

    def mouseMoveEvent(self, event):
        """鼠标移动事件"""
        if self.is_cropping and self.crop_start and event.buttons() & Qt.LeftButton:
            self.crop_end = event.pos()
            self.display_image(self.processor.image)

    def mouseReleaseEvent(self, event):
        """鼠标释放事件"""
        if self.is_cropping and self.crop_start and event.button() == Qt.LeftButton:
            self.crop_end = event.pos()
            self.display_image(self.processor.image)
            self.apply_crop_btn.setEnabled(True)
            self.statusBar.showMessage("裁剪区域已选择，点击'应用裁剪'按钮确认")

    def apply_crop(self):
        """应用裁剪"""
        if self.is_cropping and self.crop_start and self.crop_end:
            # 获取裁剪区域坐标
            x1 = min(self.crop_start.x(), self.crop_end.x())
            y1 = min(self.crop_start.y(), self.crop_end.y())
            x2 = max(self.crop_start.x(), self.crop_end.x())
            y2 = max(self.crop_start.y(), self.crop_end.y())

            # 将坐标转换为图像坐标
            img_width = self.processor.image.shape[1]
            img_height = self.processor.image.shape[0]
            label_width = self.image_display.size().width()
            label_height = self.image_display.size().height()

            scale_x = img_width / label_width
            scale_y = img_height / label_height

            x1_img = int(x1 * scale_x)
            y1_img = int(y1 * scale_y)
            x2_img = int(x2 * scale_x)
            y2_img = int(y2 * scale_y)

            # 确保坐标在有效范围内
            x1_img = max(0, min(x1_img, img_width - 1))
            y1_img = max(0, min(y1_img, img_height - 1))
            x2_img = max(0, min(x2_img, img_width - 1))
            y2_img = max(0, min(y2_img, img_height - 1))

            # 应用裁剪
            if x2_img > x1_img and y2_img > y1_img:
                self.processor.crop(x1_img, y1_img, x2_img, y2_img)
                self.display_image(self.processor.image)
                self.statusBar.showMessage("图像已裁剪")
                self.is_cropping = False
                self.crop_btn.setText("启用裁剪模式")
                self.image_display.setCursor(Qt.ArrowCursor)
                self.crop_start = None
                self.crop_end = None
            else:
                QMessageBox.warning(self, "错误", "无效的裁剪区域")

    def apply_adjust(self):
        """应用亮度和对比度调整"""
        if self.processor.image is not None:
            brightness = self.brightness_slider.value()
            contrast = self.contrast_slider.value()
            self.processor.adjust_brightness_contrast(brightness, contrast)
            self.display_image(self.processor.image)
            self.statusBar.showMessage(f"已调整亮度: {brightness}, 对比度: {contrast}")

    def apply_smooth(self):
        """应用平滑处理"""
        if self.processor.image is not None:
            method = self.smooth_combo.currentText()
            self.processor.smooth(method)
            self.display_image(self.processor.image)
            self.statusBar.showMessage(f"已应用{method}平滑处理")

    def detect_shapes(self):
        """检测形状"""
        if self.processor.image is not None:
            self.processor.detect_shapes()
            self.display_image(self.processor.image)
            self.statusBar.showMessage("形状识别完成")

    def detect_faces(self):
        """检测人脸"""
        if self.processor.image is not None:
            _, face_count = self.processor.detect_faces()
            self.display_image(self.processor.image)
            self.statusBar.showMessage(f"人脸检测完成，共检测到 {face_count} 个人脸")

    def show_about(self):
        """显示关于对话框"""
        QMessageBox.about(self, "关于", "计算机视觉开发平台\n\n"
                                      "一个基于Python和OpenCV的图像处理与计算机视觉工具\n"
                                      "支持图像加载、编辑、形状识别、人脸识别等功能")

    def closeEvent(self, event):
        """关闭事件"""
        self.stop_video()
        event.accept()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = CVPlatform()
    window.show()
    sys.exit(app.exec_())